/*
 * Copyright (c) 2009-2013 EvTech Project
 * All rights reserved.
 * 
 * This file is part of LModeller.
 *
 * LModeller is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or 
 * (at your option) any later version.
 *
 * LModeller is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LModeller.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package fi.honkalampisaatio.lmodeller.ui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.EventObject;
import java.util.Iterator;

import org.lwjgl.util.Rectangle;

import fi.honkalampisaatio.lmodeller.LModeller;
import fi.honkalampisaatio.lmodeller.LanguageResource;
import fi.honkalampisaatio.lmodeller.Logger;
import fi.honkalampisaatio.lmodeller.selection.GameModeSelectionEvent;
import fi.honkalampisaatio.lmodeller.selection.SelectionListener;
import fi.honkalampisaatio.lmodeller.selection.GameModeSelectionEvent.MODES;
import fi.honkalampisaatio.lmodeller.ui.GameButton.TEXTLOCATION;
import fi.honkalampisaatio.lwjgl.GLTexture;
import fi.honkalampisaatio.sound.VoicePlayer;
import glapp.GLApp;

public abstract class GameView {
	public enum BUTTONFLAGS {HOME, BACK, PREVIOUS, NEXT, VOICE, UPLABEL, DOWNLABEL};
	EnumSet<BUTTONFLAGS> buttonFlags;
	private SelectionListener listener = null;
	GameTextLabel downLabel;
	GameButton upLabel, voiceButton, prevButton, nextButton;
	String instruction;

	private int page = 0, maxPage = 0;
	
	ArrayList<UIElement> uiElements; 

	public GameView(EnumSet<BUTTONFLAGS> buttons)
	{
		this.buttonFlags = buttons;
		uiElements = new ArrayList<UIElement>();
	}
	
	protected abstract void refreshPage(int page);
	protected abstract void init();

	public void addSelectionListener(SelectionListener  listener) {
		this.listener = listener;
	}
	
	public void removeSelectionListener(SelectionListener listener) {
		if (this.listener == listener) {
			this.listener = null;
		}
	}
	
	protected void fireSelectionEvent(EventObject se) {
		if (this.listener != null)
		{
			this.listener.selectionEventOccurred(se);
		}
	}

	public void addComponent(UIElement element)
	{
		uiElements.add(element);
	}
	
    public void setup()
    {
    	int h = GLApp.getHeight()/10;
    	int w = GLApp.getWidth()/10;
    	if(buttonFlags.contains(BUTTONFLAGS.HOME))
    	{
    		GameButton button = new GameButton(new Rectangle((int)(w*9.1),(int)(h*9.1),
        			(int)(w*0.8),(int)(h*0.8)), GameTextures.getInstance().getTexture("HOME_BUTTON"), LModeller.actionColor
        			, null, TEXTLOCATION.UP);
    		button.setToolTipSentence(LanguageResource.getInstance().get("HOME"));
    		button.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					Logger.getInstance().log("Home button selected");
					GameModeSelectionEvent se = new GameModeSelectionEvent(this, MODES.HOME);
					fireSelectionEvent(se);
				}});
    		uiElements.add(button);
    	}
    	if(buttonFlags.contains(BUTTONFLAGS.BACK))
    	{
    		GameButton button = new GameButton(new Rectangle((int)(w*0.1),(int)(h*9.1),
        			(int)(w*0.8),(int)(h*0.8)), GameTextures.getInstance().getTexture("BACK_BUTTON")
        			, LModeller.actionColor, null, TEXTLOCATION.UP);
    		button.setToolTipSentence(LanguageResource.getInstance().get("BACK"));
    		button.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					Logger.getInstance().log("Back button selected");
					GameModeSelectionEvent se = new GameModeSelectionEvent(this, MODES.PREVIOUS);
					fireSelectionEvent(se);
				}});
    		uiElements.add(button);
    	}
    	if(buttonFlags.contains(BUTTONFLAGS.PREVIOUS))
    	{
    		prevButton = new GameButton(new Rectangle((int)(w*0.1),(int)(h*0.1),(int)(w*0.8),
        			(int)(h*0.8)), GameTextures.getInstance().getTexture("PREVIOUS_BUTTON"), LModeller.actionColor
        			, null, TEXTLOCATION.UP);
    		prevButton.setToolTipSentence(LanguageResource.getInstance().get("PREVIOUS"));
    		prevButton.setVisible(false);
    		prevButton.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					Logger.getInstance().log("Previous button selected");
					if(page>0)
					{
						page--;
				    	refreshPage(page);
					}
					if(page<=0 && prevButton != null)
					{
						prevButton.setVisible(false);
					}
					if(page<maxPage-1 && nextButton != null)
					{
						nextButton.setVisible(true);
					}
				}});
    		uiElements.add(prevButton);
    	}
    	if(buttonFlags.contains(BUTTONFLAGS.NEXT))
    	{
    		nextButton = new GameButton(new Rectangle((int)(w*9.1),(int)(h*0.1),(int)(w*0.8),
        			(int)(h*0.8)),GameTextures.getInstance().getTexture("NEXT_BUTTON"), LModeller.actionColor
        			, null, TEXTLOCATION.UP);
    		nextButton.setToolTipSentence(LanguageResource.getInstance().get("NEXT"));
    		nextButton.setVisible(false);
    		nextButton.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					Logger.getInstance().log("Next button selected");
					if(page<maxPage-1)
					{
						page++;
						refreshPage(page);
					}
					if(page>0 && prevButton != null)
					{
						prevButton.setVisible(true);
					}
					if(page>=maxPage-1 && nextButton != null)
					{
						nextButton.setVisible(false);
					}
				}});
    		uiElements.add(nextButton);
    	}
    	if(buttonFlags.contains(BUTTONFLAGS.VOICE))
    	{
    		voiceButton = new GameButton(new Rectangle((int)(w*0.1),(int)(h*4.6),(int)(w*0.6),
        			(int)(h*0.8)), GameTextures.getInstance().getTexture("VOICE_BUTTON"), LModeller.actionColor
        			, null, TEXTLOCATION.UP);
    		voiceButton.setToolTipSentence(LanguageResource.getInstance().get("SPEECH_ON"), 
    				LanguageResource.getInstance().get("SPEECH_OFF"));
    		voiceButton.setOnOff(true);
    		voiceButton.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					Logger.getInstance().log("Voice button selected");
					System.out.println("Voice button selected");
					GameButton button = (GameButton)e.getSource();
					button.toggleOnOff();
					VoicePlayer.getInstance().setOn(button.isOn());
				}});
    		uiElements.add(voiceButton);
    	}
    	if(buttonFlags.contains(BUTTONFLAGS.UPLABEL))
    	{
    		upLabel = new GameButton(new Rectangle((int)(w*1.1), (int)(h*9.1),
    				(int)(w*7.8), (int)(h*0.8)), null, LModeller.directionColor
        			, null, TEXTLOCATION.LEFT);
    		upLabel.showFrame(false);
    		uiElements.add(upLabel);
    	}
    	if(buttonFlags.contains(BUTTONFLAGS.DOWNLABEL))
    	{
    		downLabel = new GameTextLabel(new Rectangle((int)(w*1.1), (int)(h*0.1), 
        			(int)(w*7.8), (int)(h*0.8)), (int)(h*0.4), LModeller.actionColor);
    		uiElements.add(downLabel);
    	}
    	init();
    }


    public void setPageCount(int maxPage)
    {
    	page = 0;
    	this.maxPage = maxPage;
		if(page<maxPage-1 && nextButton != null)
		{
			nextButton.setVisible(true);
		}
    }
    
    public int getCurrentPage()
    {
    	return page;
    }
    
    public void setInstructionSentence(String instruction)
    {
    	this.instruction = VoicePlayer.getInstance().addVoice(instruction);
    }

    public void setUpToolTipSentence(String text)
    {
    	if(upLabel!=null)
    	{
    		upLabel.setToolTipSentence(text);
    	}
    }

    
    public void setDownToolTipSentence(String text)
    {
    	if(downLabel!=null)
    	{
    		downLabel.setToolTipSentence(text);
    	}
    }

    
    public void setUpLabelTexture(GLTexture texture)
    {
    	if(upLabel!=null)
    	{
    		upLabel.setTexture(texture);
    	}
    }
    
    public int setUpLabelText(String text)
    {
    	int fontSize = 0;
    	if(upLabel!=null)
    	{
    		fontSize = upLabel.setText(text);
    	}
    	return fontSize;
    }

    
    public String getUpLabelText()
    {
    	if(upLabel==null)
    		return null;
    	else
    		return upLabel.getText();
    }

    
    public int setDownLabelText(String text)
    {
    	int fontSize = 0;
    	if(downLabel!=null)
    	{
    		fontSize = downLabel.setText(text);
    	}
    	return fontSize;
    }

    
    public String getDownLabelText()
    {
    	if(downLabel==null)
    		return null;
    	else
    		return downLabel.getText();
    }
    

	public void setMaxFontSize(int fontSize)
	{
    	if(upLabel!=null)
    	{
    		upLabel.setMaxFontSize(fontSize);
    	}
    	if(downLabel!=null)
    	{
    		downLabel.setMaxFontSize(fontSize);
    	}
	}
    
	public void render()
	{
		Iterator<UIElement> it = uiElements.iterator();
		while(it.hasNext())
		{
			UIElement uiElement = it.next();
			uiElement.render();
		}
	}
	
	public void mouseDown(int x, int y)
	{
		Iterator<UIElement> it = uiElements.iterator();
		while(it.hasNext())
		{
			UIElement uiElement = it.next();
			uiElement.mouseDown(x, y);
		}
	}

	
	public void mouseMove(int x, int y)
	{
		Iterator<UIElement> it = uiElements.iterator();
		while(it.hasNext())
		{
			UIElement uiElement = it.next();
			uiElement.mouseMove(x, y);
		}
	}
	
	public void mouseUp(int x, int y)
	{
	}
	
	public void viewOpened()
	{
		//refresh button states
		voiceButton.setOnOff(VoicePlayer.getInstance().isOn());
		playInstruction();
	}
	
	protected void playInstruction()
	{
		if(instruction!=null && !instruction.isEmpty())
			VoicePlayer.getInstance().play(instruction);
	}
}
